﻿using System;
using System.Globalization;
using System.Web;

namespace Wiki.Web
{
    public static class IHttpResponseExtensionMethods
    {
        public static void Created(this IHttpResponse arg)
        {
            arg.Created(null as string);
        }

        public static void Created(this IHttpResponse arg, string location)
        {
            arg.StatusCode = 201; // Created
            if (!location.IsNullOrEmpty())
            {
                arg.AppendHeader("Content-Location", location);
                arg.ContentType = "text/html";
                arg.Write("<html>");
                arg.Write("<head><title>Page created successfully</title>");
                arg.Write(String.Format(CultureInfo.InvariantCulture, "<meta http-equiv=\"refresh\" content=\"0;url={0}\">", location));
                arg.Write("</head><body>");
                arg.Write("<h1>Page created successfully</h1>");
                arg.Write("<p>You should be redirected automatically. If not, click the following link:</p>");
                arg.Write("<ul><li><a href=\"");
                arg.Write(location);
                arg.Write("\">");
                arg.Write(HttpUtility.HtmlEncode(location));
                arg.Write("</a></li></ul>");
                arg.Write("</body>");
                arg.Write("</html>");
            }
        }

        public static void SeeOther(this IHttpResponse arg, string location)
        {
            arg.StatusCode = 303; // See Other
            arg.AppendHeader("Location", location);
            arg.ContentType = "text/html";
            arg.Write("<html>");
            arg.Write("<head><title>The information you requested has been found</title></head>");
            arg.Write("<body>");
            arg.Write("<h1>The information you requested has been found</h1>");
            arg.Write("<p><a href=\"");
            arg.Write(location);
            arg.Write("\">");
            arg.Write(HttpUtility.HtmlEncode(location));
            arg.Write("</a></p>");
            arg.Write("</body>");
            arg.Write("</html>");

            arg.Cache.SetCacheability(HttpCacheability.Public);
            arg.Cache.SetExpires(DateTime.UtcNow.AddDays(1));
        }

        public static void SeeOther(this IHttpResponse arg, string location, DateTime? lastModified)
        {
            arg.StatusCode = 303; // See Other
            arg.AppendHeader("Location", location);
            arg.ContentType = "text/html";
            arg.Write("<html>");
            arg.Write("<head><title>The information you requested has been found</title></head>");
            arg.Write("<body>");
            arg.Write("<h1>The information you requested has been found</h1>");
            arg.Write("<p><a href=\"");
            arg.Write(location);
            arg.Write("\">");
            arg.Write(HttpUtility.HtmlEncode(location));
            arg.Write("</a></p>");
            arg.Write("</body>");
            arg.Write("</html>");

            if (lastModified != null)
            {
                arg.Cache.SetCacheability(HttpCacheability.Public);
                arg.Cache.SetLastModified(lastModified.Value);
                arg.Cache.VaryByHeaders.AcceptTypes = true;
            }
        }

        public static void MethodNotAllowed(this IHttpResponse arg, string allow)
        {
            arg.StatusCode = 405; // Method Not Allowed
            arg.AppendHeader("Allow", allow);
            arg.AppendHeader("Content-Language", "en");
            arg.ContentType = "text/html";
            arg.Write("<html>");
            arg.Write("<head><title>Sorry, the HTTP method used is not allowed</title></head>");
            arg.Write("<body>");
            arg.Write("<h1>Sorry, the HTTP method used is not allowed</h1>");
            arg.Write("<p>The following methods are allowed:</p>");
            arg.Write("<ul>");
            foreach (string method in allow.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
            {
                arg.Write("<li>");
                arg.Write(method);
                arg.Write("</li>");
            }
            arg.Write("</ul>");
            arg.Write("</body>");
            arg.Write("</html>");
        }

        public static void NoContent(this IHttpResponse arg)
        {
            arg.StatusCode = 204; // No Content
        }

        public static void NotAcceptable(this IHttpResponse arg)
        {
            arg.StatusCode = 406; // Not Acceptable
            arg.AppendHeader("Content-Language", "en");
            arg.ContentType = "text/html";
            arg.Write("<html>");
            arg.Write("<head><title>Sorry, the requested media type is not available</title></head>");
            arg.Write("<body>");
            arg.Write("<h1>Sorry, the requested media type is not available</h1>");
            arg.Write("</body>");
            arg.Write("</html>");
        }

        public static void NotFound(this IHttpResponse arg)
        {
            arg.StatusCode = 404; // Not Found
            arg.AppendHeader("Content-Language", "en");
            arg.ContentType = "text/html";
            arg.Write("<html>");
            arg.Write("<head><title>Sorry, the page you requested was not found</title></head>");
            arg.Write("<body>");
            arg.Write("<h1>Sorry, the page you requested was not found</h1>");
            arg.Write("<p>You may have followed a broken link or mistyped the web address.</p>");
            arg.Write("<ul>");
            arg.Write("<li>Return to the <a href=\"/\">home page</a></li>");
            arg.Write("<li>Find answers in the <a href=\"/help\">help section</a></li>");
            arg.Write("<li>Search");
            arg.Write("<form method=\"get\" action=\"/search\" style=\"display:inline\">");
            arg.Write("<input type=\"text\" name=\"q\" size=\"16\" value=\"\"/>");
            arg.Write("<input type=\"submit\" value=\"search\"/>");
            arg.Write("</form>");
            arg.Write("</li>");
            arg.Write("</ul>");
            arg.Write(new String(' ', 400));
            arg.Write("</body>");
            arg.Write("</html>");
        }

        public static void Options(this IHttpResponse arg, string allow)
        {
            arg.StatusCode = 200; // OK
            arg.AppendHeader("Allow", allow);
        }

        public static void UnsupportedMediaType(this IHttpResponse arg, params string[] supportedMediaTypes)
        {
            arg.StatusCode = 415; // Unsupported Media Type
            arg.AppendHeader("Content-Language", "en");
            arg.ContentType = "text/html";
            arg.Write("<html>");
            if ((supportedMediaTypes == null) || (supportedMediaTypes.Length == 0))
            {
                arg.Write("<head><title>Sorry, there are no supported media types</title></head>");
            }
            else
            {
                arg.Write("<head><title>Sorry, the media type you provided is not supported</title></head>");
            }

            arg.Write("<body>");
            if ((supportedMediaTypes == null) || (supportedMediaTypes.Length == 0))
            {
                arg.Write("<h1>Sorry, there are no supported media types</h1>");
            }
            else
            {
                arg.Write("<h1>Sorry, the media type you provided is not supported</h1>");
            }

            if ((supportedMediaTypes != null) || (supportedMediaTypes.Length != 0))
            {
                if (supportedMediaTypes.Length == 1)
                {
                    arg.Write("<p>The following media type is supported:</p>");
                }
                else
                {
                    arg.Write("<p>The following media types are supported:</p>");
                }

                arg.Write("<ul>");
                foreach (string type in supportedMediaTypes)
                {
                    arg.Write("<li>");
                    arg.Write(HttpUtility.HtmlEncode(type));
                    arg.Write("</li>");
                }
                arg.Write("</ul>");
            }

            arg.Write("</body>");
            arg.Write("</html>");
        }
    }
}